package me.sdevil507.org.controller;

import lombok.extern.slf4j.Slf4j;
import me.sdevil507.biz.common.exceptions.PhoneNumberExistedException;
import me.sdevil507.biz.common.sms.captcha.enums.CaptchaType;
import me.sdevil507.biz.common.sms.captcha.service.CaptchaService;
import me.sdevil507.biz.common.sysdict.po.SysDict;
import me.sdevil507.biz.common.sysdict.service.SysdictService;
import me.sdevil507.org.dto.*;
import me.sdevil507.org.mapper.OrgUserMapper;
import me.sdevil507.org.po.OrgDeptPo;
import me.sdevil507.org.po.OrgKeywordPo;
import me.sdevil507.org.po.OrgPo;
import me.sdevil507.org.po.OrgUserPo;
import me.sdevil507.org.service.OrgDeptService;
import me.sdevil507.org.service.OrgService;
import me.sdevil507.org.service.OrgUserService;
import me.sdevil507.supports.helper.Md5PasswordHelper;
import me.sdevil507.supports.jpa.PageConvertCallBack;
import me.sdevil507.supports.jpa.PageResultDTO;
import me.sdevil507.supports.jpa.PageResultGenerator;
import me.sdevil507.supports.result.ApiResultDTO;
import me.sdevil507.supports.result.ApiResultGenerator;
import me.sdevil507.supports.shiro.enums.RoleType;
import me.sdevil507.supports.shiro.helper.OrgAccountHelper;
import me.sdevil507.supports.status.ApiStatusCode;
import me.sdevil507.supports.util.AESUtil;
import me.sdevil507.systemAssist.Constant.SystemAssistConstant;
import me.sdevil507.systemAssist.systemLog.annotation.OperLog;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * API用户Controller
 *
 * @author sdevil507
 * created on 2020/4/20
 */
@RestController
@RequestMapping("/api/org/user")
@Slf4j
public class OrgUserController {

    @Autowired
    private OrgUserService orgUserService;

    @Autowired
    private Md5PasswordHelper md5PasswordHelper;

    @Autowired
    private OrgUserMapper orgUserMapper;

    @Autowired
    private OrgService orgService;

    @Autowired
    private SysdictService sysdictService;

    @Autowired
    private CaptchaService captchaService;

    @Autowired
    private OrgDeptService orgDeptService;

    /**
     * 更改密码
     *
     * @param dto 入参dto
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.ORG, operClassify = SystemAssistConstant.systemAssistClassify.SECURITY, operModule = SystemAssistConstant.systemAssistModule.MODIFY_PWD, operDesc = "")
    @PostMapping("/changePassword")
    public ApiResultDTO orgChangePassword(@RequestBody @Valid OrgUserChangePasswordParamsDto dto) {
        String phoneNumber = OrgAccountHelper.getUsername();
        OrgUserPo orgUserPo = orgUserService.readOneByPhoneNumber(phoneNumber);
        // 校验原始密码
        if (!Objects.equals(AESUtil.encryptPassword(dto.getOldPassword()), orgUserPo.getPassword())) {
            return ApiResultGenerator.create(ApiStatusCode.ACCOUNT_OLD_PWD_INVALID.getCode(), ApiStatusCode.ACCOUNT_OLD_PWD_INVALID.getDescription());
        }
        // 执行更改密码
        String encryptNewPassword = AESUtil.encryptPassword(dto.getNewPassword());
        orgUserService.updatePasswordByPhoneNumber(encryptNewPassword, phoneNumber);
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }

    /**
     * 获取用户个人信息
     *
     * @return 个人信息
     */
    @GetMapping("/info")
    public ApiResultDTO info() {
        String phoneNumber = OrgAccountHelper.getUsername();
        OrgUserPo orgUserPo = orgUserService.readOneByPhoneNumber(phoneNumber);
        OrgUserResultDto orgUserResultDto = orgUserMapper.po2dto(orgUserPo);
        if(RoleType.MGR.name().equals(OrgAccountHelper.getOrgType())){
//            OrgPo orgPo = orgService.readOne(OrgAccountHelper.getOrgId());
            OrgDeptPo orgDeptPo = orgDeptService.getOne(OrgAccountHelper.getDeptId());
            orgUserResultDto.setOrgId(orgDeptPo.getId());
//            orgUserResultDto.setOrgLogo(orgPo.getLogo());
            orgUserResultDto.setOrgName(orgDeptPo.getTitle());
//            orgUserResultDto.setIntro(orgPo.getIntro());
//            orgUserResultDto.setPreDomainName(orgPo.getPreDomainName());
//            orgUserResultDto.setMgrUserId(orgPo.getPresetMgr() != null ? orgPo.getPresetMgr().getId() : null);
            orgUserResultDto.setOrgType(RoleType.MGR.name());
//            orgUserResultDto.setKeywords(orgPo.getKeywords().stream().map(OrgKeywordPo::getName).collect(Collectors.joining("/")));
            //获取研究领域
//            String domain = orgPo.getDomain();
//            if(!StringUtils.isEmpty(domain)){
//                String[] domainArr = domain.split(",");
//                String domains = "";
//                for (String val : domainArr) {
//                    List<SysDict> sysDicts = sysdictService.findByTypeKeyAndValue("ResearchDomain", val);
//                    if (sysDicts.size() > 0) {
//                        domains += sysDicts.get(0).getDname() + ",";
//                    }
//                }
//                orgUserResultDto.setDomains(domains.length() > 0 ? domains.substring(0, domains.length()-1) : domains);
//            }
        } else{
            orgUserResultDto.setOrgType(RoleType.EXPERT.name());
        }

        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), orgUserResultDto);
    }

    /**
     * 根据手机号获取用户信息
     *
     * @param dto 入参手机号
     * @return 信息
     */
    @PostMapping("/readByPhoneNumber")
    public ApiResultDTO readByPhoneNumber(@RequestBody OrgUserParamsDto dto) {
        OrgUserPo orgUserPo = orgUserService.readOneByPhoneNumber(dto.getPhoneNumber());
        Map<String, Object> result = new HashMap<>(2);
        if (orgUserPo != null) {
            OrgUserResultDto orgUserResultDto = orgUserMapper.po2dto(orgUserPo);
            result.put("type", true);
            result.put("info", orgUserResultDto);
        } else {
            result.put("type", false);
            result.put("info", null);
        }

        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), result);
    }

    /**
     * 创建机构下管理用户
     *
     * @param dto 用户dto
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.ORG, operClassify = SystemAssistConstant.systemAssistClassify.SECURITY, operModule = SystemAssistConstant.systemAssistModule.USER_ADD, operDesc = "")
    @PostMapping("/create")
    @RequiresPermissions(value={"org:user:view","plat:user:add"}, logical= Logical.OR)
    public ApiResultDTO create(@RequestBody OrgUserParamsDto dto) {
        // 查询用户是否存在
        try {
            orgUserService.create(dto);
        } catch (PhoneNumberExistedException e) {
            return ApiResultGenerator.create(ApiStatusCode.ACCOUNT_EXISTED.getCode(), ApiStatusCode.ACCOUNT_EXISTED.getDescription());
        }
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }

    /**
     * 修改个人信息
     *
     * @param dto 参数
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.ORG, operClassify = SystemAssistConstant.systemAssistClassify.SECURITY, operModule = SystemAssistConstant.systemAssistModule.USER_UPDATE, operDesc = "")
    @PostMapping("/update")
    @RequiresPermissions(value={"org:user:view","plat:user:edit"}, logical= Logical.OR)
    public ApiResultDTO update(@RequestBody OrgUserParamsDto dto) {
        try {
            orgUserService.update(dto);
        } catch (PhoneNumberExistedException e) {
            return ApiResultGenerator.create(ApiStatusCode.ACCOUNT_EXISTED.getCode(), ApiStatusCode.ACCOUNT_EXISTED.getDescription());
        }
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }

    /**
     * 删除机构下用户
     *
     * @param dto 参数
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.ORG, operClassify = SystemAssistConstant.systemAssistClassify.SECURITY, operModule = SystemAssistConstant.systemAssistModule.USER_DELETE, operDesc = "")
    @PostMapping("/delete")
    @RequiresPermissions(value={"org:user:view","plat:user:delete"}, logical= Logical.OR)
    public ApiResultDTO delete(@RequestBody OrgUserParamsDto dto) {
        orgUserService.delete(dto);
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }

    /**
     * 分页获取信息列表
     *
     * @param dto 入参参数
     * @return 分页数据
     */
    @SuppressWarnings("Convert2Lambda")
    @RequestMapping(value = "/readAllByPage", method = RequestMethod.POST)
    @ResponseBody
    public ApiResultDTO readAllByPage(@RequestBody OrgUserMergeParamsDto dto) {
        dto.getSearchDto().setOrgId(OrgAccountHelper.getOrgId());
        Page<OrgUserPo> pagePos = orgUserService.readAllByPage(dto.getSearchDto(), dto.getPageDto(), dto.getSortDto());
        for (OrgUserPo pagePo : pagePos.getContent()) {
            List<OrgDeptPo> tempList = new ArrayList<>();
            for (OrgDeptPo dept : pagePo.getDepts()) {
                if (dept.getOrg().getId().equals(OrgAccountHelper.getOrgId())) {
                    tempList.add(dept);
                }
            }
            pagePo.setDepts(tempList);
        }
        PageResultDTO<OrgUserResultDto> pageResultDto = PageResultGenerator.convert(pagePos, new PageConvertCallBack<OrgUserResultDto, OrgUserPo>() {
            @Override
            public List<OrgUserResultDto> exec(List<OrgUserPo> list) {
                return orgUserMapper.pos2dtos(list);
            }
        });
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), pageResultDto);
    }

    /**
     * 分页获取信息列表
     *
     * @param dto 入参参数
     * @return 分页数据
     */
    @SuppressWarnings("Convert2Lambda")
    @RequiresPermissions(value={"org:user:view","plat:user:view"}, logical= Logical.OR)
    @RequestMapping(value = "/readAllDeptUserByPage", method = RequestMethod.POST)
    @ResponseBody
    public ApiResultDTO readAllDeptUserByPage(@RequestBody OrgUserMergeParamsDto dto) {
        Page<OrgUserPo> pagePos = orgUserService.readAllByPage(dto.getSearchDto(), dto.getPageDto(), dto.getSortDto());
        PageResultDTO<OrgUserResultDto> pageResultDto = PageResultGenerator.convert(pagePos, new PageConvertCallBack<OrgUserResultDto, OrgUserPo>() {
            @Override
            public List<OrgUserResultDto> exec(List<OrgUserPo> list) {
                return orgUserMapper.pos2dtos(list);
            }
        });
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription(), pageResultDto);
    }

//    /**
//     * 重置密码
//     *
//     * @param dto 重置密码dto
//     * @return 执行反馈
//     */
//    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.ORG, operClassify = SystemAssistConstant.systemAssistClassify.SECURITY, operModule = SystemAssistConstant.systemAssistModule.USER_RESETPWD, operDesc = "")
//    @RequestMapping(value = "/resetPassword", method = RequestMethod.POST)
//    public ApiResultDTO resetPassword(@RequestBody OrgUserParamsDto dto) {
//        orgUserService.resetPassword(dto.getPhoneNumber(), dto.getPassword());
//        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
//    }

    /**
     * 重置密码
     *
     * @param dto 入参
     * @return 执行反馈
     */
    @OperLog(operTerminal = SystemAssistConstant.systemAssistTerminal.PLATFORM, operClassify = SystemAssistConstant.systemAssistClassify.SECURITY, operModule = SystemAssistConstant.systemAssistModule.USER_RESETPWD, operDesc = "")
    @PostMapping("/resetPassword")
    @RequiresPermissions(value={"org:user:view","plat:user:resetpwd"}, logical= Logical.OR)
    public ApiResultDTO resetPassword(@RequestBody @Valid OrgUserRestPasswordParamsDTO dto) {
        if(!dto.isAdminFlag()){
            boolean checkCaptchaState = captchaService.check(CaptchaType.FORGET_PASSWORD, dto.getPhoneNumber(), dto.getCode());
            if (!checkCaptchaState) {
                // 如果验证码校验失败
                return ApiResultGenerator.create(ApiStatusCode.CAPTCHA_INVALID.getCode(), ApiStatusCode.CAPTCHA_INVALID.getDescription());
            }
        }
        // 执行密码重置
        orgUserService.resetPassword(dto.getPhoneNumber(), dto.getNewPassword());
        return ApiResultGenerator.create(ApiStatusCode.SUCCESS.getCode(), ApiStatusCode.SUCCESS.getDescription());
    }
}
